﻿using System.Diagnostics;
using System.Diagnostics.Contracts;

namespace System
{
    //public delegate void EventsHandler<T>(object sender, EventArgs<T> e);

    /// <summary>Аргумент события с типизированным параметром</summary>
    /// <typeparam name="TArgument">Тип параметра аргумента</typeparam>
    public class EventArgs<TArgument> : EventArgs
    {
        /* ------------------------------------------------------------------------------------------ */

        /* ------------------------------------------------------------------------------------------ */

        /// <summary>Параметр аргумента</summary>
        public TArgument Argument { get; set; }

        /* ------------------------------------------------------------------------------------------ */

        /// <summary>Новый аргумент события с типизированным параметром</summary>
        /// <param name="Argument">Параметр аргумента</param>
        [DebuggerStepThrough]
        public EventArgs(TArgument Argument)
        {
            Contract.Requires(Argument != null);
            this.Argument = Argument;
        }

        /* ------------------------------------------------------------------------------------------ */

        /// <summary>
        /// Возвращает объект <see cref="T:System.String"/>, который представляет текущий объект <see cref="T:System.Object"/>.
        /// </summary>
        /// <returns>Объект <see cref="T:System.String"/>, представляющий текущий объект <see cref="T:System.Object"/>.</returns>
        /// <filterpriority>2</filterpriority>
        [DebuggerStepThrough]
        public override string ToString() { return Argument.ToString(); }

        /* ------------------------------------------------------------------------------------------ */

        /// <summary>Оператор неявного преобразования аргумента события к типу содержащегося в нём значения </summary>
        /// <param name="Args">Аргумент события</param>
        /// <returns>Хранимый объект</returns>
        [DebuggerStepThrough]
        public static implicit operator TArgument(EventArgs<TArgument> Args) { return Args.Argument; }

        /// <summary>
        /// Оgератор неявного преобразования типа зранимого значения в обёртку из аргумента события, содержащего это значение
        /// </summary>
        /// <param name="Argument">Объект аргумента события</param>
        /// <returns>Аргумент события</returns>
        [DebuggerStepThrough]
        public static implicit operator EventArgs<TArgument>(TArgument Argument) { return new EventArgs<TArgument>(Argument); }

        /* ------------------------------------------------------------------------------------------ */
    }

    /// <summary>Аргумент события с двумя типизированными параметрами</summary>
    /// <typeparam name="TArgument1">Тип первого параметра</typeparam>
    /// <typeparam name="TArgument2">Тип второго параметра</typeparam>
    public class EventArgs<TArgument1, TArgument2> : EventArgs
    {
        /// <summary>Первый аргумент</summary>
        public TArgument1 Argument1 { get; set; }

        /// <summary>Второй аргумент</summary>
        public TArgument2 Argument2 { get; set; }

        /// <summary>Новый аргумент события с двумя параметрами</summary>
        [DebuggerStepThrough]
        protected EventArgs() { }

        /// <summary>Новый аргумент события с двумя параметрами</summary>
        /// <param name="Argument1">Первый аргумент события</param>
        /// <param name="Argument2">Второй аргумент события</param>
        [DebuggerStepThrough]
        public EventArgs(TArgument1 Argument1, TArgument2 Argument2)
        {
            this.Argument1 = Argument1;
            this.Argument2 = Argument2;
        }

        [DebuggerStepThrough]
        public static implicit operator TArgument1(EventArgs<TArgument1, TArgument2> Args) { return Args.Argument1; }

        [DebuggerStepThrough]
        public static implicit operator TArgument2(EventArgs<TArgument1, TArgument2> Args) { return Args.Argument2; }
    }

    public class EventArgs<TArgument1, TArgument2, TArgument3> : EventArgs
    {
        public TArgument1 Argument1 { get; set; }

        public TArgument2 Argument2 { get; set; }

        public TArgument3 Argument3 { get; set; }

        [DebuggerStepThrough]
        public EventArgs() { }

        [DebuggerStepThrough]
        public EventArgs(TArgument1 Argument1, TArgument2 Argument2, TArgument3 Argument3)
        {
            this.Argument1 = Argument1;
            this.Argument2 = Argument2;
            this.Argument3 = Argument3;
        }
    }
}